import React, { Component } from 'react';
import { Chart, Axis, Geom, Label, Facet, View } from 'bizcharts';
import ResizeObserver from 'resize-observer-polyfill';
import {
  themeLight,
  themeDark,
  commonConfig,
  axisConfig,
  legendConfig,
  barConfig,
  fitFontSize,
} from '../config';
import styles from '../index.less';

const {
  defaultTheme,
  defaultFontFamily,
  defaultTickCount,
  defaultChartUnitFontSize,
  defaultValueOffset,
  defaultValueFontSize,
  defaultPaddingTop,
} = commonConfig;
const { defaultXLabelFontSize, defaultXLabelOffset, defaultYLabelFontSize } = axisConfig;
const {
  defaultLegendOffsetY,
  defaultLegendFontSize,
  defaultLegendLineHeight,
  defaultLegendItemGap,
  defaultLegendMarkerCircle,
} = legendConfig;
const {
  defaultBarAdjust,
  defaultBarShape,
  defaultBarWidth,
  defaultBarOpacity,
  defaultColTitleFontSize,
} = barConfig;

export default class FacetBar extends Component {
  state = {
    height: 0,
    viewportScale: window.viewportScale,
  };

  componentDidMount() {
    this.resizeObserver();
    window.addEventListener('resize', this.resize, { passive: true });
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.resize);
  }

  handleRoot = n => {
    this.root = n;
  };

  resize = () => {
    this.setState({ viewportScale: window.viewportScale });
  };

  resizeObserver() {
    const ro = new ResizeObserver(entries => {
      const { width, height } = entries[0].contentRect;
      this.setState(preState => {
        if (preState.width !== width || preState.height !== height) {
          return {
            height,
          };
        }
        return null;
      });
    });
    if (this.root) {
      ro.observe(this.root);
    }
  }

  render() {
    const { height: stateHeight, viewportScale } = this.state;
    const { theme = defaultTheme } = this.props;
    const {
      defaultColors,
      defaultColor,
      defaultChartUnitColor,
      defaultLineColor,
      defaultGridColor,
      defaultValueColor,
      defaultXLabelColor,
      defaultYLabelColor,
      defaultColTitleColor,
    } = theme === 'dark' ? themeDark : themeLight;
    const {
      chartPadding = 'auto',
      facetPadding = 0,
      fields,
      showTitle,
      cols,
      style = {},

      height: propsHeight,
      forceFit = true,
      data = [],
      hiddenYLabel = false, // 是否隐藏y轴标签
      showValue = false, // 柱子顶端显示数值
      hiddenXLabel = false, // 是否隐藏x轴标签
      xLabelOffset = defaultXLabelOffset, // x轴标签距x轴距离
      xLabelAutoRotate = false, // 是否自动旋转
      geomStyle = {}, // 为Geom添加自定义样式，设置cursor之类的

      groupField, // 分组字段（Legend）
      colors = defaultColors, // 分组颜色数组
      color = defaultColor,

      x = 'x', // x轴字段名
      y = 'y', // y轴字段名
      adjust = defaultBarAdjust,
      shape = defaultBarShape,

      size = defaultBarWidth, // 每根柱子的宽度
      valueOffset = defaultValueOffset, // 柱状图数值距柱子顶端距离

      unit = '',
      showYUnit = false, // 为y轴标签添加单位
      showTooltipUnit = true, // 为tooltip添加单位
      chartUnitPosition, // 设置图表总单位位置
      chartUnitColor = defaultChartUnitColor, // 图表总单位颜色
      chartUnitFontSize = defaultChartUnitFontSize, // 图表总单位字体大小

      fontSize, // 同时设置以下几种字体大小，下面的设置将无效
      xLabelFontSize = defaultXLabelFontSize, // x轴标签字体大小
      yLabelFontSize = defaultYLabelFontSize, // y轴标签字体大小
      valueFontSize = defaultValueFontSize, // 柱状图数值字体大小

      tickCount = defaultTickCount, // 网格线条数

      xScale = {},
      yScale = {},
    } = this.props;

    const scale = {
      [x]: {
        type: 'cat',
        ...xScale,
      },
      [y]: {
        formatter(val) {
          return (val || val === 0) && (showYUnit ? val.toFixed(0) + unit : val.toFixed(0));
        },
        tickCount,
        ...yScale,
      },
    };

    const height = propsHeight || stateHeight;

    return (
      <div
        className={styles.bar}
        style={{ height: height * viewportScale, ...style }}
        ref={this.handleRoot}
        key={this.root}
      >
        <Chart
          scale={scale}
          height={height * viewportScale}
          forceFit={forceFit}
          data={data}
          padding={chartPadding}
          ref={this.handleRoot}
          key={this.root}
        >
          <Facet
            type="list"
            fields={fields}
            padding={facetPadding}
            showTitle={showTitle}
            cols={cols}
            colTitle={{
              offsetY: -15 * viewportScale,
              style: {
                fill: defaultColTitleColor,
                fontSize: fitFontSize(defaultColTitleFontSize),
                fontFamily: defaultFontFamily,
                textAlign: 'center',
              },
            }}
          >
            <View>
              <Axis
                name={x}
                visible={!hiddenXLabel}
                line={{
                  stroke: defaultLineColor,
                  lineWidth: 1,
                }}
                tickLine={null}
                label={{
                  autoRotate: xLabelAutoRotate,
                  offset: xLabelOffset * viewportScale,
                  textStyle: {
                    fill: defaultXLabelColor,
                    fontSize: fitFontSize(fontSize || xLabelFontSize),
                    fontFamily: defaultFontFamily,
                  },
                }}
              />
              <Axis
                name={y}
                visible={!hiddenYLabel}
                label={{
                  textStyle: {
                    fill: defaultYLabelColor,
                    fontSize: fitFontSize(fontSize || yLabelFontSize),
                    fontFamily: defaultFontFamily,
                  },
                }}
                grid={{
                  lineStyle: {
                    stroke: defaultGridColor,
                    lineWidth: 1,
                    // lineDash: [4, 0],
                  },
                }}
              />
              <Geom
                style={geomStyle}
                type="interval"
                position={`${x}*${y}`}
                color={groupField ? [groupField, colors] : color}
                size={size * viewportScale}
                opacity={defaultBarOpacity}
                adjust={adjust}
                shape={shape}
              >
                {showValue && (
                  <Label
                    content={y}
                    offset={valueOffset * viewportScale}
                    textStyle={{
                      fill: defaultValueColor,
                      fontSize: fitFontSize(fontSize || valueFontSize),
                      fontFamily: defaultFontFamily,
                    }}
                  />
                )}
              </Geom>
            </View>
          </Facet>
        </Chart>
      </div>
    );
  }
}
